home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / dev / mui / MCC_Tron0_7.lha / MCC_Tron / Source / MUI / mccheader.c next >
C/C++ Source or Header  |  1996-10-25  |  12KB  |  497 lines

  1. /*****************************************************************************
  2.  
  3. This code serves as a basis for writing a library-based MUI custom class
  4. (xyz.mcc) and its preferences editor (xyz.mcp).
  5.  
  6. You need to define a few things in your main source file, then include
  7. this file and then continue with your classes methods. The order is
  8. important, mccheader.c must be the first code-generating module.
  9.  
  10. Things to be defined before mccheader.c is included:
  11.  
  12. (1)  UserLibID     - version string for your class. must follow normal $VER: string conventions.
  13. (2)  VERSION       - version number of the class. must match the one given in the $VER: string.
  14. (3)  REVISION      - revision number of the class. must match the one given in the $VER: string.
  15. (4)  CLASS         - Name of your class, ".mcc" or ".mcp" must always be appended.
  16.  
  17. (5)  SUPERCLASS    - superclass of your class.
  18. (6)  struct Data   - instance data structure.
  19. (7)  _Dispatcher   - your dispatcher function.
  20.  
  21. (8)  SUPERCLASSP   - Superclass of the preferences class, must be MUIC_Mccprefs or a subclass.
  22. (9)  struct DataP  - instance data structure of preferences class.
  23. (10) _DispatcherP  - dispatcher for the preferences class.
  24.  
  25. Items (1) to (4) must always be defined. If you create a stand-alone
  26. custom class (*.mcc) without preferences editor, also define (5), (6)
  27. and (7). Name your class and the resulting ouptut file "Myclass.mcc".
  28.  
  29. If you create a preferences class (*.mcp) for a custom class, define
  30. (8), (9) and (10) instead of (5), (6) and (7). Name your class and the
  31. resulting output file "Myclass.mcp".
  32.  
  33. If you create a custom class with included preferences editor, define
  34. all the above. Note that in this case, the name of your class and the
  35. resulting output file is always "Myclass.mcc". MUI will automatically
  36. recognize that there's also a "Myclass.mcp" included. Having a builtin
  37. preferences class reduces the need for a second file but increases the
  38. size and memory consuption of the class.
  39.  
  40. If your class needs custom initialization (e.g. opening other
  41. libraries), you can define
  42.     ClassInit
  43.     ClassExit
  44. to point to custom functions. These functions need to have the prototypes
  45.     BOOL ClassInitFunc(struct Library *base);
  46.     VOID ClassExitFunc(struct Library *base);
  47. and will be called right after the class has been created and right
  48. before the class is being deleted. If your init func returns FALSE,
  49. the custom class will be unloaded immediately.
  50.  
  51. Define the minimum version of muimaster.libray in MASTERVERSION. If you
  52. don't define MASTERVERSION, it will default to MUIMASTER_VMIN from the
  53. mui.h include file.
  54.  
  55. This code automatically defines and initializes the following variables:
  56.     struct Library *MUIMasterBase;
  57.     struct Library *SysBase;
  58.     struct Library *UtilityBase;
  59.     struct Library *DOSBase;
  60.     struct Library *GfxBase;
  61.     struct Library *IntuitionBase;
  62.     struct Library *MUIClassBase;       /* your classes library base */
  63.     struct MUI_CustomClass *ThisClass;  /* your custom class */
  64.     struct MUI_CustomClass *ThisClassP; /* your preferences class */
  65.  
  66. Example: Myclass.c
  67.     #define CLASS      MUIC_Myclass // name of class, e.g. "Myclass.mcc"
  68.     #define SUPERCLASS MUIC_Area    // name of superclass
  69.     struct Data
  70.     {
  71.         LONG          MyData;
  72.         struct Foobar MyData2;
  73.         // ...
  74.     };
  75.     #define UserLibID "$VER: Myclass.mcc 17.53 (11.11.96)"
  76.     #define VERSION   17
  77.     #define REVISION  53
  78.     #include "mccheader.c"
  79.     ULONG ASM SAVEDS _Dispatcher(REG(a0) struct IClass *cl,
  80.                                  REG(a2) Object *obj,
  81.                                  REG(a1) Msg msg)
  82.     {
  83.         // ...
  84.     }
  85.  
  86. Compiling and linking with SAS-C can look like this:
  87.     Myclass.mcc: Myclass.c
  88.         sc $(CFLAGS) $*.c OBJNAME $*.o
  89.         slink to $@ from $*.o lib $(LINKERLIBS) $(LINKERFLAGS)
  90.  
  91. Note well that we don't use SAS library creation feature here, it simply
  92. sucks too much. It's not much more complicated to do the library
  93. initialziation ourselves and we have better control over everything.
  94.  
  95. Make sure to read the whole source to get some interesting comments
  96. and some understanding on how libraries are created!
  97.  
  98. *****************************************************************************/
  99.  
  100.  
  101. /* a few includes... */
  102.  
  103. #include <exec/types.h>
  104. #include <exec/memory.h>
  105. #include <exec/libraries.h>
  106. #include <exec/semaphores.h>
  107. #include <exec/resident.h>
  108. #include <dos/dos.h>
  109. #include <clib/exec_protos.h>
  110. #include <pragmas/exec_sysbase_pragmas.h>
  111.  
  112.  
  113. /* The name of the class will also become the name of the library. */
  114. /* We need a pointer to this string in our ROMTag (see below). */
  115.  
  116. static const char UserLibName[] = CLASS;
  117.  
  118.  
  119. /* Here's our global data, described above. */
  120.  
  121. struct Library *MUIClassBase;
  122. struct Library *MUIMasterBase;
  123. struct Library *SysBase;
  124. struct Library *UtilityBase;
  125. struct Library *DOSBase;
  126. struct Library *GfxBase;
  127. struct Library *IntuitionBase;
  128.  
  129. #ifdef SUPERCLASS
  130. struct MUI_CustomClass *ThisClass;
  131. #endif
  132.  
  133. #ifdef SUPERCLASSP
  134. struct MUI_CustomClass *ThisClassP;
  135. #endif
  136.  
  137. #ifdef _DCC
  138. #define REG(x) __ ## x
  139. #define ASM
  140. #define SAVEDS __geta4
  141. #else
  142. #define REG(x) register __ ## x
  143. #define ASM    __asm
  144. #define SAVEDS __saveds
  145. #endif
  146.  
  147.  
  148. /* Our library structure, consisting of a struct Library, a segment pointer */
  149. /* and a semaphore. We need the semaphore to protect init/exit stuff in our */
  150. /* open/close functions */
  151.  
  152. struct LibraryHeader
  153. {
  154.     struct Library         lh_Library;
  155.     BPTR                   lh_Segment;
  156.     struct SignalSemaphore lh_Semaphore;
  157. };
  158.  
  159.  
  160. /* Prototypes for all library functions */
  161.  
  162. struct LibraryHeader * ASM LibInit   (REG(a0) BPTR Segment);
  163. BPTR                   ASM LibExpunge(REG(a6) struct LibraryHeader *base);
  164. struct LibraryHeader * ASM LibOpen   (REG(a6) struct LibraryHeader *base);
  165. BPTR                   ASM LibClose  (REG(a6) struct LibraryHeader *base);
  166. LONG                   ASM LibNull   (VOID);
  167. ULONG           SAVEDS ASM MCC_Query (REG(d0) LONG which);
  168.  
  169.  
  170. /* Prototypes for a few sub-functions */
  171.  
  172. BOOL ASM UserLibInit   (REG(a6) struct Library *base);
  173. BOOL ASM UserLibExpunge(REG(a6) struct Library *base);
  174. BOOL ASM UserLibOpen   (REG(a6) struct Library *base);
  175. BOOL ASM UserLibClose  (REG(a6) struct Library *base);
  176.  
  177.  
  178. /* This is the librarie's jump table */
  179.  
  180. static const APTR LibVectors[] =
  181. {
  182.     LibOpen,
  183.     LibClose,
  184.     LibExpunge,
  185.     LibNull,
  186.     MCC_Query,
  187.     (APTR)-1
  188. };
  189.  
  190.  
  191. /* Dummy entry point and LibNull() function all in one */
  192.  
  193. LONG ASM LibNull(VOID)
  194. {
  195.     return(NULL);
  196. }
  197.  
  198.  
  199. /* Here's what makes us a library. */
  200.  
  201. static const struct Resident ROMTag =
  202. {
  203.     RTC_MATCHWORD,
  204.     &ROMTag,
  205.     &ROMTag + 1,
  206.     0,
  207.     VERSION,
  208.     NT_LIBRARY,
  209.     0,
  210.     UserLibName,
  211.     UserLibID,
  212.     LibInit
  213. };
  214.  
  215.  
  216. #undef D
  217. #undef bug
  218. #undef bugg
  219.  
  220. #ifdef DEBUG
  221.  
  222. #ifndef __KMEL
  223. extern void kprintf(const char *, ...);
  224. #endif
  225. #define D(flags,x) { ##x; }
  226. #define bug kprintf("%-12.12s %-17.17s: ",__FILE__,__FUNC__); kprintf
  227. #define bugg kprintf
  228.  
  229. #else
  230.  
  231. #define D(flags,x)
  232. #define bug
  233. #define bugg
  234.  
  235. #endif /* DEBUG */
  236.  
  237.  
  238.  
  239. /******************************************************************************/
  240. /* Standard Library Functions, all of them are called in Forbid() state.      */
  241. /******************************************************************************/
  242.  
  243. struct LibraryHeader * ASM SAVEDS LibInit(REG(a0) BPTR Segment)
  244. {
  245.     struct LibraryHeader *base;
  246.  
  247.     SysBase = *((struct Library **)4);
  248.  
  249.     D(DBF_LIB,bug("start...\n"));
  250.  
  251.     #ifdef __SASC
  252.     #ifdef _M68040
  253.     if (!(((struct ExecBase *)SysBase)->AttnFlags & AFF_68040)) return(NULL);
  254.     #endif
  255.     #ifdef _M68030
  256.     if (!(((struct ExecBase *)SysBase)->AttnFlags & AFF_68030)) return(NULL);
  257.     #endif
  258.     #ifdef _M68020
  259.     if (!(((struct ExecBase *)SysBase)->AttnFlags & AFF_68020)) return(NULL);
  260.     #endif
  261.     #endif
  262.  
  263.     if (base = (struct LibraryHeader *)MakeLibrary((APTR)LibVectors,NULL,NULL,sizeof(struct LibraryHeader),NULL))
  264.     {
  265.         base->lh_Library.lib_Node.ln_Type = NT_LIBRARY;
  266.         base->lh_Library.lib_Node.ln_Name = (char *)UserLibName;
  267.         base->lh_Library.lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
  268.         base->lh_Library.lib_Version      = VERSION;
  269.         base->lh_Library.lib_Revision     = REVISION;
  270.         base->lh_Library.lib_IdString     = (char *)UserLibID;
  271.  
  272.         base->lh_Segment  = Segment;
  273.  
  274.         InitSemaphore(&base->lh_Semaphore);
  275.  
  276.         AddLibrary((struct Library *)base);
  277.     }
  278.     else
  279.     {
  280.         D(DBF_LIB,bug("\7MakeLibrary() failed\n"));
  281.     }
  282.  
  283.     return(base);
  284. }
  285.  
  286.  
  287. BPTR ASM SAVEDS LibExpunge(REG(a6) struct LibraryHeader *base)
  288. {
  289.     struct Library *SysBase = *((struct Library **)4);
  290.     BPTR rc;
  291.  
  292.     D(DBF_LIB,bug("OpenCount=%ld\n",base->lh_Library.lib_OpenCnt));
  293.  
  294.     if (base->lh_Library.lib_OpenCnt)
  295.     {
  296.         base->lh_Library.lib_Flags |= LIBF_DELEXP;
  297.         D(DBF_LIB,bug("Setting LIBF_DELEXP\n"));
  298.         return(NULL);
  299.     }
  300.  
  301.     Remove((struct Node *)base);
  302.     rc = base->lh_Segment;
  303.     FreeMem((BYTE *)base - base->lh_Library.lib_NegSize,base->lh_Library.lib_NegSize + base->lh_Library.lib_PosSize);
  304.  
  305.     return(rc);
  306. }
  307.  
  308.  
  309. struct LibraryHeader * ASM SAVEDS LibOpen(REG(a6) struct LibraryHeader *base)
  310. {
  311.     struct Library *SysBase = *((struct Library **)4);
  312.     struct LibraryHeader *rc;
  313.  
  314.     base->lh_Library.lib_OpenCnt++;
  315.     base->lh_Library.lib_Flags &= ~LIBF_DELEXP;
  316.  
  317.     D(DBF_LIB,bug("OpenCount=%ld\n",base->lh_Library.lib_OpenCnt));
  318.  
  319.     ObtainSemaphore(&base->lh_Semaphore);
  320.  
  321.     if (UserLibOpen((struct Library *)base))
  322.     {
  323.         rc = base;
  324.     }
  325.     else
  326.     {
  327.         rc = NULL;
  328.         base->lh_Library.lib_OpenCnt--;
  329.         D(DBF_LIB,bug("\7UserLibOpen() failed\n"));
  330.     }
  331.  
  332.     ReleaseSemaphore(&base->lh_Semaphore);
  333.  
  334.     return(rc);
  335. }
  336.  
  337.  
  338. BPTR ASM SAVEDS LibClose(REG(a6) struct LibraryHeader *base)
  339. {
  340.     struct Library *SysBase = *((struct Library **)4);
  341.     BPTR rc = NULL;
  342.  
  343.     D(DBF_LIB,bug("OpenCount=%ld %s\n",base->lh_Library.lib_OpenCnt,base->lh_Library.lib_OpenCnt==0 ? "\7ERROR" : ""));
  344.  
  345.     ObtainSemaphore(&base->lh_Semaphore);
  346.     UserLibClose((struct Library *)base);
  347.     ReleaseSemaphore(&base->lh_Semaphore);
  348.  
  349.     if (--base->lh_Library.lib_OpenCnt == 0)
  350.     {
  351.         if (base->lh_Library.lib_Flags & LIBF_DELEXP)
  352.         {
  353.             rc = LibExpunge(base);
  354.         }
  355.     }
  356.  
  357.     return(rc);
  358. }
  359.  
  360.  
  361. BOOL ASM SAVEDS UserLibOpen(REG(a6) struct Library *base)
  362. {
  363.     ULONG ASM _Dispatcher(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg);
  364.     ULONG ASM _DispatcherP(REG(a0) struct IClass *cl, REG(a2) Object *obj, REG(a1) Msg msg);
  365.     BOOL ClassInitFunc(struct Library *base);
  366.  
  367.     D(DBF_CLASS,bug("%ld\n",base->lib_OpenCnt));
  368.  
  369.     if (base->lib_OpenCnt!=1)
  370.         return(TRUE);
  371.  
  372.     #ifndef MASTERVERSION
  373.     #define MASTERVERSION MUIMASTER_VMIN
  374.     #endif
  375.  
  376.     if (MUIMasterBase = OpenLibrary("muimaster.library",MASTERVERSION))
  377.     {
  378.         #ifdef SUPERCLASS
  379.         if (ThisClass = MUI_CreateCustomClass(base,SUPERCLASS,NULL,sizeof(struct Data),_Dispatcher))
  380.         #endif
  381.         {
  382.             #ifdef SUPERCLASSP
  383.             if (ThisClassP = MUI_CreateCustomClass(base,SUPERCLASSP,NULL,sizeof(struct DataP),_DispatcherP))
  384.             #endif
  385.             {
  386.                 #ifdef SUPERCLASS
  387.                 #define THISCLASS ThisClass
  388.                 #else
  389.                 #define THISCLASS ThisClassP
  390.                 #endif
  391.  
  392.                 UtilityBase   = THISCLASS->mcc_UtilityBase;
  393.                 DOSBase       = THISCLASS->mcc_DOSBase;
  394.                 GfxBase       = THISCLASS->mcc_GfxBase;
  395.                 IntuitionBase = THISCLASS->mcc_IntuitionBase;
  396.  
  397.                 #ifndef ClassInit
  398.                 return(TRUE);
  399.                 #else
  400.                 if (ClassInitFunc(base))
  401.                 {
  402.                     return(TRUE);
  403.                 }
  404.  
  405.                 #ifdef SUPERCLASSP
  406.                 MUI_DeleteCustomClass(ThisClassP);
  407.                 ThisClassP = NULL;
  408.                 #endif
  409.  
  410.                 #endif
  411.             }
  412.             #ifdef SUPERCLASSP
  413.             #ifdef SUPERCLASS
  414.             MUI_DeleteCustomClass(ThisClass);
  415.             ThisClass = NULL;
  416.             #endif
  417.             #endif
  418.         }
  419.         CloseLibrary(MUIMasterBase);
  420.         MUIMasterBase = NULL;
  421.     }
  422.  
  423.     D(DBF_CLASS,bug("fail.: %08lx %s\n",base,base->lib_Node.ln_Name));
  424.  
  425.     return(FALSE);
  426. }
  427.  
  428.  
  429. BOOL ASM SAVEDS UserLibClose(REG(a6) struct Library *base)
  430. {
  431.     VOID ClassExitFunc(struct Library *base);
  432.  
  433.     D(DBF_CLASS,bug("%ld\n",base->lib_OpenCnt));
  434.  
  435.     if (base->lib_OpenCnt==1)
  436.     {
  437.         #ifdef ClassExit
  438.         ClassExitFunc(base);
  439.         #endif
  440.  
  441.         #ifdef SUPERCLASSP
  442.         if (ThisClassP)
  443.         {
  444.             MUI_DeleteCustomClass(ThisClassP);
  445.             ThisClassP = NULL;
  446.         }
  447.         #endif
  448.  
  449.         #ifdef SUPERCLASS
  450.         if (ThisClass)
  451.         {
  452.             MUI_DeleteCustomClass(ThisClass);
  453.             ThisClass = NULL;
  454.         }
  455.         #endif
  456.  
  457.         if (MUIMasterBase)
  458.         {
  459.             CloseLibrary(MUIMasterBase);
  460.             MUIMasterBase = NULL;
  461.         }
  462.     }
  463.  
  464.     return(TRUE);
  465. }
  466.  
  467.  
  468. ULONG SAVEDS ASM MCC_Query(REG(d0) LONG which)
  469. {
  470.     switch (which)
  471.     {
  472.         #ifdef SUPERCLASS
  473.         case 0: return((ULONG)ThisClass);
  474.         #endif
  475.  
  476.         #ifdef SUPERCLASSP
  477.         case 1: return((ULONG)ThisClassP);
  478.         #endif
  479.  
  480.         #ifdef PREFSIMAGEOBJECT
  481.         case 2:
  482.         {
  483.             Object *obj = PREFSIMAGEOBJECT;
  484.             return((ULONG)obj);
  485.         }
  486.         #endif
  487.  
  488.         #ifdef ONLYGLOBAL
  489.         case 3:
  490.         {
  491.             return(TRUE);
  492.         }
  493.         #endif
  494.     }
  495.     return(NULL);
  496. }
  497.